﻿using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using SymulatorEthernetWPF.SimObjects;
using SymulatorEthernetWPF.SimObjects.Devices;
using SymulatorEthernetWPF.SimObjects.Wires;

namespace SymulatorEthernetWPF.Shared
{
    internal static class StaticFunctions
    {
        public static List<WireBenderHandler> SortWireBenderPoints(List<WireBenderHandler> wireBenderPoints, NetworkInterface networkInterfaceA, NetworkInterface networkInterfaceB, WireBenderHandler wireBenderHandler)
        {
            if (wireBenderPoints.Count > 0)
            {
                double minLength = GetTriangleHeight(networkInterfaceA.Position, wireBenderPoints[0].Position,
                                                     wireBenderHandler.Position);
                int position = 0;

                for (int i = 0; i < wireBenderPoints.Count - 1; i++)
                {
                    if (
                        GetTriangleHeight(wireBenderPoints[i].Position, wireBenderPoints[i + 1].Position,
                                          wireBenderHandler.Position) < minLength)
                    {
                        minLength = GetTriangleHeight(wireBenderPoints[i].Position, wireBenderPoints[i + 1].Position,
                                                      wireBenderHandler.Position);
                        position = i + 1;
                    }
                }
                if (
                    GetTriangleHeight(wireBenderPoints[wireBenderPoints.Count - 1].Position, networkInterfaceB.Position,
                                      wireBenderHandler.Position) < minLength)
                {
                    position = wireBenderPoints.Count;
                }
                wireBenderPoints.Insert(position, wireBenderHandler);
                return wireBenderPoints;
            }
            wireBenderPoints.Add(wireBenderHandler);
            return wireBenderPoints;
        }

        public static Vector GetVector(Point a, Point b)
        {
            return new Vector(a.X - b.X, a.Y - b.Y);
        }

        private static double MulVector(Vector a, Vector b)
        {
            return (a.X*b.Y - (a.Y*b.X));
        }

        private static double GetTriangleHeight(Point a, Point b, Point c)
        {
            return 0.5*Math.Abs(MulVector(GetVector(a, c), GetVector(b, c)))/(0.5*GetLength(a, b));
        }

        public static double GetLength(Point a, Point b)
        {
            return Math.Sqrt(Math.Pow(a.X - b.X, 2) + Math.Pow(a.Y - b.Y, 2));
        }
        public static double getVectorLength(Vector a)
        {
            return Math.Sqrt(Math.Pow(a.X, 2) + Math.Pow(a.Y, 2));
        }

        public static byte[] Compress(byte[] raw)
        {
            using (var memory = new MemoryStream())
            {
                using (var gzip = new GZipStream(memory, CompressionMode.Compress, true))
                {
                    gzip.Write(raw, 0, raw.Length);
                }
                return memory.ToArray();
            }
        }

        public static byte[] Decompress(byte[] gzip)
        {
            using (var stream = new GZipStream(new MemoryStream(gzip), CompressionMode.Decompress))
            {
                const int size = 4096;
                var buffer = new byte[size];
                using (var memory = new MemoryStream())
                {
                    int count;
                    do
                    {
                        count = stream.Read(buffer, 0, size);
                        if (count > 0)
                        {
                            memory.Write(buffer, 0, count);
                        }
                    } while (count > 0);
                    return memory.ToArray();
                }
            }
        }

        public static ImageSource ResizeImage(ImageSource source)
        {
            var rect = new Rect(0, 0, 64, 48);

            var drawingVisual = new DrawingVisual();

            using (DrawingContext drawingContext = drawingVisual.RenderOpen())
            {
                drawingContext.DrawImage(source, rect);
            }

            var resizedImage = new RenderTargetBitmap(
                (int) rect.Width, (int) rect.Height, // Resized dimensions

                96, 96, // Default DPI values

                PixelFormats.Default); // Default pixel format

            resizedImage.Render(drawingVisual);
            return resizedImage;
        }
    }
}